#ifndef DRV_PID_H
#define DRV_PID_H

#include "stm32g4xx.h"

/**
 * @brief PID算法形式枚举
 */
typedef enum
{
    PID_POSITIONAL_FORM = 0, // 位置式
    PID_INCREMENTAL_FORM     // 增量式
} PidForm_t;

/**
 * @brief PID实例
 */
typedef struct
{
    /* 一系列参数 */
    float kp;                   // 比例常数
    float ki;                   // 积分常数
    float kd;                   // 微分常数
    PidForm_t form;             // 算法形式
    float target;               // 目标值
    float output;               // 输出值
    float currError;            // 当前偏差
    float lastError;            // 上次偏差
    float prevError;            // 上两次偏差
    float sumError;             // 累计偏差
    float integralLimit;        // 积分限幅
    FunctionalState windupFlag; // 积分饱和标志位
    float maxOutput;            // 输出上限
    float minOutput;            // 输出下限
} Pid_t;

/**
 * @brief PID初始化结构体
 */
typedef struct
{
    /* 一系列参数 */
    float kp;            // 比例常数
    float ki;            // 积分常数
    float kd;            // 微分常数
    PidForm_t form;      // 算法形式
    float integralLimit; // 积分限幅
    float maxOutput;     // 输出上限
    float minOutput;     // 输出下限
} PidInit_t;

/**
 * @brief PID参数消息结构体
 */
typedef struct
{
    float target; // 目标值
    float kp;     // 比例常数
    float ki;     // 积分常数
    float kd;     // 微分常数
} PidArgsMsg_t;

/**
 * @brief 初始化一个PID实例
 * @param pid: PID实例
 * @param pidInit: PID初始化结构体
 * @return None
 */
void PID_Init(Pid_t *pid, PidInit_t *pidInit);

/**
 * @brief 设置PID的目标值
 * @param pid: PID实例
 * @param target: 目标值
 * @return None
 */
void PID_SetTarget(Pid_t *pid, const float target);

/**
 * @brief 设置PID的参数
 * @param pid: PID实例
 * @param kp: kp值
 * @param ki: ki值
 * @param kd: kd值
 * @return None
 */
void PID_SetArgs(Pid_t *pid, const float kp, const float ki, const float kd);

/**
 * @brief 获取PID的输出值
 * @param pid: PID实例
 * @return PID的输出值
 */
float PID_GetOutput(Pid_t *pid);

/**
 * @brief 获取PID的目标值
 * @param pid: PID实例
 * @return PID的目标值
 */
float PID_GetTarget(Pid_t *pid);

/**
 * @brief 重置PID实例
 * @param pid: PID实例
 * @return None
 */
void PID_Reset(Pid_t *pid);

/**
 * @brief 进行一次位置式PID计算
 * @param pid: PID实例
 * @param feedback: 反馈值
 * @return None
 */
void PID_PositionalCalc(Pid_t *pid, const float feedback);

/**
 * @brief 进行一次增量式PID计算
 * @param pid: PID实例
 * @param feedback: 反馈值
 * @return None
 */
void PID_IncrementalCalc(Pid_t *pid, const float feedback);

/**
 * @brief 对PID实例进行计算
 * @param pid: PID实例
 * @param feedback: 反馈值
 * @return None
 */
void PID_Calculate(Pid_t *pid, const float feedback);

#endif //DRV_PID_H
